package utils

import (
	"bytes"
	"context"
	"encoding/gob"
	"errors"
	"github.com/beego/beego/v2/client/cache"
	"github.com/beego/beego/v2/core/logs"
	beego "github.com/beego/beego/v2/server/web"
	"time"
)

var cc cache.Cache

func InitCache() {
	cacheConfig, _ := beego.AppConfig.String("cache")
	cc = nil

	if "file" == cacheConfig {
		initFile()
	} else {
		initMemory()
	}
}

func initFile() {
	var err error
	cc, err = cache.NewCache("file", `{"CachePath":"/cache","FileSuffix":".cache","DirectoryLevel":"2","EmbedExpiry":"1200"}`)

	if err != nil {
		logs.Info("缓存初始化异常", err)
	}
}

func initMemory() {
	var err error
	cc, err = cache.NewCache("memory", `{"interval":6000}`)

	if err != nil {
		logs.Info("缓存初始化异常", err)
	}
}

func SetCache(key string, value interface{}, timeout int) error {
	data, err := Encode(value)
	if err != nil {
		return err
	}
	if cc == nil {
		return errors.New("cc is nil")
	}

	defer func() {
		if r := recover(); r != nil {
			//fmt.Println("set cache error caught: %v\n", r)
			cc = nil
		}
	}()
	timeouts := time.Duration(timeout) * time.Second
	err = cc.Put(context.Background(), key, data, timeouts)
	if err != nil {
		//fmt.Println("Cache失败，key:", key)
		return err
	} else {
		//fmt.Println("Cache成功，key:", key)
		return nil
	}
}

func GetCache(key string, to interface{}) error {
	if cc == nil {
		return errors.New("cc is nil")
	}

	defer func() {
		if r := recover(); r != nil {
			//fmt.Println("get cache error caught: %v\n", r)
			cc = nil
		}
	}()

	data, err := cc.Get(context.Background(), key)
	if IsEmpty(data) || data == nil || err != nil {
		return errors.New("Cache不存在")
	}
	// log.Pinkln(data)
	err = Decode(data.([]byte), to)
	if err != nil {
		//fmt.Println("获取Cache失败", key, err)
	} else {
		//fmt.Println("获取Cache成功", key)
	}

	return err
}

func DelCache(key string) error {
	if cc == nil {
		return errors.New("cc is nil")
	}

	defer func() {
		if r := recover(); r != nil {
			//fmt.Println("get cache error caught: %v\n", r)
			cc = nil
		}
	}()

	err := cc.Delete(context.Background(), key)
	if err != nil {
		return errors.New("Cache删除失败")
	} else {
		//fmt.Println("删除Cache成功 " + key)
		return nil
	}
}

// --------------------
// Encode
// 用gob进行数据编码
//
func Encode(data interface{}) ([]byte, error) {
	buf := bytes.NewBuffer(nil)
	enc := gob.NewEncoder(buf)
	err := enc.Encode(data)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

// -------------------
// Decode
// 用gob进行数据解码
//
func Decode(data []byte, to interface{}) error {
	buf := bytes.NewBuffer(data)
	dec := gob.NewDecoder(buf)
	return dec.Decode(to)
}
